package redecolaborativa.testes;

import static org.junit.Assert.*;

import java.util.Calendar;
import java.util.LinkedList;

import org.junit.Before;
import org.junit.Test;
//import redecolaborativa.enums.Categoria;
import redecolaborativa.excecoes.*;
import redecolaborativa.objetos.*;
import redecolaborativa.sistema.Gerenciador;
import redecolaborativa.sistema.Usuario;

public class TesteEmprestimo {
	private Emprestimo umEmprestimo;
	private Usuario beneficiado;
	private Usuario donoItem;
	private Item item;
	private LinkedList<String> categorias = new LinkedList<String>();
	
	Gerenciador gerenciador;
	
	@Before
	public void iniciaTeste() throws Exception {
		Emprestimo.resetaGeradorID();
		gerenciador = Gerenciador.getInstance();
		beneficiado = new Usuario("Lilia", "liliars", "Santo Antonio");
		donoItem = new Usuario("Isa", "isalr", "Bodocongo");
		categorias.add("Filme"); categorias.add("Livro");
		item = new Item("nome", categorias, "descricao", donoItem);
		umEmprestimo = new Emprestimo(beneficiado, item, 4);
	}
	
	@Test
	public void testaConstrutor() throws Exception {
		try {
			umEmprestimo = new Emprestimo(null, item, 4);
			fail("Esperava excecao de beneficiado invalido.");
		} catch(BeneficiadoInvalidoException ex) {
			assertEquals("Mensagem errada", "O beneficiado nao pode ser nulo.", ex.getMessage());
		} try {
			umEmprestimo = new Emprestimo(beneficiado, null, 4);
			fail("Esperava excecao de item invalido.");
		} catch(ItemInvalidoException ex) {
			assertEquals("Mensagem errada", "O item desejado nao pode ser nulo.", ex.getMessage());
		} try {
			umEmprestimo = new Emprestimo(beneficiado, item, -5);
			fail("Esperava excecao de numero negativo.");
		} catch(NumeroNegativoException ex) {
			assertEquals("Mensagem errada", "Duracao inválida", ex.getMessage());
		}
	}
	
	@Test
	public void testResetaGeradorID() throws Exception {
		umEmprestimo.iniciar();
		Item item2 = new Item("Harry Potter", categorias, "JK", donoItem);
		Emprestimo emp = new Emprestimo(beneficiado, item, 3);
		emp.iniciar();
		assertEquals(2, emp.getIDEmprestimo());
		Emprestimo.resetaGeradorID();
		Emprestimo emp2 = new Emprestimo(beneficiado, item2, 4);
		emp2.iniciar();
		assertEquals(1, emp2.getIDEmprestimo());
	}
	
	@Test
	public void testaGetDeEmprestimo() throws Exception {
		Item item2 = new Item("nome", categorias, "descricao", donoItem);
		assertEquals("Beneficiado errado", "Lilia", umEmprestimo.getBeneficiado().getNome());
		assertEquals("Item diferente", item2, umEmprestimo.getItem());
		assertEquals(4, umEmprestimo.getTempoPrevisto());
	}
	
	@Test
	public void testaIniciar() throws Exception {
		assertTrue(umEmprestimo.getItem().estaDisponivel());
		umEmprestimo.iniciar();
		assertFalse(umEmprestimo.getItem().estaDisponivel());
		assertNotNull(umEmprestimo.getDataInicial());
		assertEquals(1, umEmprestimo.getIDEmprestimo());
	}
	
	@Test 
	public void testaAndamento() throws Exception {
		umEmprestimo.iniciar();
		assertEquals("Andamento", umEmprestimo.andamento());
		umEmprestimo.finalizar();
		assertEquals("Completado", umEmprestimo.andamento());
		assertNotSame("Cancelado", umEmprestimo.andamento());
	}
	
	@Test
	public void testaFinalizar() throws Exception {
		umEmprestimo.iniciar();
		assertFalse(umEmprestimo.getItem().estaDisponivel());
		umEmprestimo.finalizar();
		assertTrue(umEmprestimo.getItem().estaDisponivel());
	}
	
	@Test
	public void testaCanceladoAntesDaData() throws Exception {
		//Verifica que um emprestimo foi cancelado antes do tempo
		umEmprestimo.iniciar();
		item.getDono().gerenteDeEmprestimos().adiciona(umEmprestimo);
		item.getDono().requisitarDevolucaoDeItem(item);
		umEmprestimo.finalizar();
		umEmprestimo.verificaCancelado();
		assertTrue(umEmprestimo.canceladoAntes());
	}
	
	@Test
	public void testaCanceladoDepoisDaData() throws Exception {
		//Verifica que um emprestimo nao foi cancelado antes do tempo
		umEmprestimo.iniciar();
		item.getDono().gerenteDeEmprestimos().adiciona(umEmprestimo);
		item.getDono().requisitarDevolucaoDeItem(item);
		umEmprestimo.finalizar();
		//setando a data de requisicao
		umEmprestimo.getDataInicial().add(Calendar.DAY_OF_YEAR,  -(umEmprestimo.getTempoPrevisto()) - 4);
		umEmprestimo.verificaCancelado();
		assertFalse(umEmprestimo.canceladoAntes());
	}
	
	@Test
	public void testaEmprestimoFoiTerminado() throws Exception {
		beneficiado.requisitarAmizade(donoItem); donoItem.aprovarAmizade(beneficiado);
		donoItem.cadastrarItem("xpto", "filme", "xpto");
		Item item = donoItem.gerenteDeItens().getItens().get(0);
		beneficiado.requisitarItem(item, 2);
		donoItem.aceitarSolicitacaoDeItem(item);
		Emprestimo emprestimo = donoItem.gerenteDeEmprestimos().getEmprestimo(item);
		assertFalse(emprestimo.foiTerminado());
		beneficiado.devolverItem(item);
		donoItem.confirmaDevolucao(item);
		assertTrue(emprestimo.foiTerminado());
	}
}